#!/bin/bash

set -euo pipefail

# Store PIDs of all the subprocesses
pids=()

echo -e "..... Cluster Logging must-gather script started .....\n"

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source ${SCRIPT_DIR}/common
BASE_COLLECTION_PATH="${1:-/must-gather}"
BASE_COLLECTION_PATH=$(cd "$(dirname -- $BASE_COLLECTION_PATH)" >/dev/null; pwd -P)/$(basename -- "$BASE_COLLECTION_PATH")
LOGGING_NS="${2:-openshift-logging}"
LOGFILE_NAME="${3:-gather-debug.log}"
LOGFILE_PATH="${BASE_COLLECTION_PATH}/${LOGFILE_NAME}" # must-gather/gather-debug.log

mkdir -p "${BASE_COLLECTION_PATH}"
cd $BASE_COLLECTION_PATH
log "must-gather logs are located at: '${LOGFILE_PATH}'"

mkdir ${BASE_COLLECTION_PATH}/cache-dir||:
export KUBECACHEDIR=${BASE_COLLECTION_PATH}/cache-dir

# cluster-scoped resources
cluster_resources=(ns/openshift-operator-lifecycle-manager)

# cluster logging operator namespace
cluster_resources+=(ns/$LOGGING_NS)

# elasticsearch operator namespace
cluster_resources+=(ns/openshift-operators-redhat)

# multi-forwarder namespaces
for kind in $(oc get crd -A -o custom-columns=:.metadata.name | grep clusterlogforwarder); do
  namespaces=$(oc get $kind -A -o custom-columns=:.metadata.namespace | sort -u)
  for multi in ${namespaces} ; do
      # add to the list of namespaces
      cluster_resources+=(ns/$multi)
      log "Adding namespace '$multi' to cluster resources list" >> "${LOGFILE_PATH}"

      # get collector resources from the namespace
      log "Inspecting collector resources in namespace '$multi'" | tee "${LOGFILE_PATH}"
      ${SCRIPT_DIR}/gather_collection_resources "$BASE_COLLECTION_PATH" "$multi" 2>&1 >> "${LOGFILE_PATH}"
  done
done

# cluster-scoped resources
cluster_resources+=(nodes)
cluster_resources+=(clusterroles)
cluster_resources+=(clusterrolebindings)
cluster_resources+=(persistentvolumes)
cluster_resources+=(clusterversion)
cluster_resources+=(machineconfigpool)
cluster_resources+=(customresourcedefinitions)

log "- BEGIN inspecting cluster resources..." | tee "${LOGFILE_PATH}"
for cr in "${cluster_resources[@]}" ; do
  log "-- BEGIN inspecting cluster resource ${cr} ..." >> "${LOGFILE_PATH}"
  oc adm inspect --cache-dir=${KUBECACHEDIR} --dest-dir="${BASE_COLLECTION_PATH}" "${cr}"  >> "${LOGFILE_PATH}" 2>&1 &
  pids+=($!)
done
log "- END inspecting cluster resources..." >> "${LOGFILE_PATH}"

# namespace-scoped resources
resources="pods,roles,rolebindings,configmaps,serviceaccounts,events,installplans,subscriptions,clusterserviceversions,logfilemetricexporter"

log "BEGIN inspecting namespaced resources ..." | tee "${LOGFILE_PATH}"

for namespace in ${cluster_resources}    ; do
  # grab all our namespaces -- openshift-logging, openshift-operator-lifecycle-manager, openshift-operators-redhat
  # should also include any multi-forwarder namespaces found above
  if [[ $namespace == ns/* ]]; then
    ns=${namespace#ns/}  # remove "ns/" prefix
      log "-- BEGIN inspecting ${ns}/${resources} ..." >> "${LOGFILE_PATH}"
      oc adm inspect --cache-dir=${KUBECACHEDIR} --dest-dir="${BASE_COLLECTION_PATH}" -n "$ns" "$resources" 2>&1 | tee "${LOGFILE_PATH}"  &
      pids+=($!)
  fi

done
log "END inspecting namespaced resources ..." >> "${LOGFILE_PATH}"


default_clo_found="$(oc -n "$LOGGING_NS" get deployment cluster-logging-operator --ignore-not-found --no-headers)"

if [ "$default_clo_found" != "" ] ; then
  log "BEGIN gathering default CLO resources ..." | tee "${LOGFILE_PATH}"
  ${SCRIPT_DIR}/gather_cluster_logging_operator_resources "$BASE_COLLECTION_PATH" "$LOGGING_NS" 2>&1 >> "${LOGFILE_PATH}"
  log "END gathering default CLO resources ..." >> "${LOGFILE_PATH}"
else
  log "Skipping collection inspection.  No default CLO found" 2>&1 | tee "${LOGFILE_PATH}"
fi

loki_crd=$(oc get crd -A -o custom-columns=:.metadata.name | grep lokistack)||
if [ "$loki_crd" != "" ] ; then
  found_lokistack="$(oc -n $LOGGING_NS get lokistack.loki.grafana.com --ignore-not-found --no-headers)"
  if [ "$found_lokistack" != "" ] ; then

    log "BEGIN gathering lokistack resources ..." | tee "${LOGFILE_PATH}"
    ${SCRIPT_DIR}/gather_logstore_resources "$BASE_COLLECTION_PATH" "lokistack" 2>&1 | tee "${LOGFILE_PATH}"
    log "END gathering logstorage resources ..."  >> "${LOGFILE_PATH}"
  else
    log "Skipping logstorage inspection.  No deployment found" 2>&1 | tee "${LOGFILE_PATH}"
  fi
fi

# Check if PID array has any values, if so, wait for them to finish
if [ ${#pids[@]} -ne 0 ]; then
    log "Waiting on subprocesses to finish execution."
    wait "${pids[@]}"
fi

exit 0
